package edu.osu.cse.c651.cryptochess;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.osu.cse.c651.cryptochess.db.UserDatabaseHelper;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputType;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;

/**
 * This activity manages the accounts on the phone. It provides ways for the users to
 * add and log into existing accounts.
 * 
 * @author Katherine Tornwall
 */
public class LoginActivity extends Activity {
	
	/**
	 * The button the user will click to log into an account.
	 */
	private Button loginButton;
	/**
	 * The password field used to log into the account. Shows up as dots for extra
	 * security.
	 */
	private EditText loginPasswordField;
	/**
	 * The layout containing the loginButton and loginPasswordField.
	 */
	private LinearLayout loginLayout;

	/**
	 * Sets up the various controls used for the application. This includes the add
	 * account button, as well as the add account dialog and error messages that are
	 * used when adding an account or logging in. This also sets up the click listener
	 * to add the login controls to an account when tapped.<br /><br />
	 * 
	 * {@inheritDoc}
	 * 
	 * @author Katherine Tornwall
	 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.login_screen);
        Button buttonAddAccount = (Button)findViewById(R.id.buttonAddAccount);
        ListView loginUserList = (ListView)findViewById(R.id.listViewLoginUsers);
        
        ArrayList<User> userArray = new ArrayList<User>();
		UserAdapter userAdapter = new UserAdapter(this, R.layout.user_layout, userArray);
		loginUserList.setAdapter(userAdapter);
        
		loginUserList.setOnItemClickListener(new ListView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
				// Create the button if it hasn't already appeared once in the program
				if(loginLayout == null) {
					loginLayout = new LinearLayout(LoginActivity.this);
					loginLayout.setOrientation(LinearLayout.HORIZONTAL);
					if(loginButton == null) {
						loginButton = new Button(LoginActivity.this);
						loginButton.setText("Login");
						LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
						buttonParams.gravity = Gravity.CENTER_VERTICAL;
						loginButton.setLayoutParams(buttonParams);
					}
					if(loginPasswordField == null) {
						loginPasswordField = new EditText(LoginActivity.this);
						LinearLayout.LayoutParams editParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
						editParams.weight = 1.0f;
						loginPasswordField.setLayoutParams(editParams);
						loginPasswordField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
					}
					loginLayout.addView(loginPasswordField);
					loginLayout.addView(loginButton);
				}
				// Remove the views from their parent
				if(loginLayout.getParent() != null) {
					((LinearLayout)loginLayout.getParent()).removeView(loginLayout);
				}
				
				// Set the button listener
				final User u = (User)parent.getItemAtPosition(pos);
				loginButton.setOnClickListener(new Button.OnClickListener() {
					@Override
					public void onClick(View v) {
						// Check that the password is correct
						UserDatabaseHelper db = new UserDatabaseHelper(LoginActivity.this);
						boolean passCheck = db.checkPassword(u.getUsername(), loginPasswordField.getText().toString());
						
						if(passCheck) {
							Intent intent = new Intent(LoginActivity.this, FindGameActivity.class);
							intent.putExtra("user", u);
							LoginActivity.this.startActivity(intent);
						} else {
							LayoutInflater inflater = getLayoutInflater();
							final View layout = inflater.inflate(R.layout.add_error_message, null);
							final PopupWindow errorWindow = new PopupWindow(layout, LayoutParams.FILL_PARENT, 
									LayoutParams.FILL_PARENT, true);
							
							TextView errorText = (TextView)layout.findViewById(R.id.errorText);
							errorText.setText("That password is incorrect.");
							
							Button okButton = (Button)layout.findViewById(R.id.errorButtonOK);
							okButton.setOnClickListener(new Button.OnClickListener() {
								@Override
								public void onClick(View v) {
									errorWindow.dismiss();
								}
							});
							
							errorWindow.showAtLocation(layout, Gravity.CENTER, 0, 0);
						}
					} 
				});
				
				// Add the views back to the item that was clicked
				((LinearLayout)view).addView(loginLayout);
			}		
		});

		buttonAddAccount.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Inflate the view from a predefined XML layout
				LayoutInflater inflater = getLayoutInflater();
				final View layout = inflater.inflate(R.layout.add_account, null);
				final PopupWindow addUser = new PopupWindow(layout, LayoutParams.FILL_PARENT, 
						LayoutParams.FILL_PARENT, true);
				
				final Spinner icons = (Spinner)layout.findViewById(R.id.addAccountIcon);
				IconAdapter adapter = new IconAdapter(LoginActivity.this, 
						getIconList(),
						R.layout.icon,
						new String[] {"Icon"}, 
						new int[] {R.id.spinnerIcon});
				icons.setAdapter(adapter);
				
				Button addButton = (Button)layout.findViewById(R.id.addAccountButtonCreate);
				addButton.setOnClickListener(new Button.OnClickListener() {
					@Override
					public void onClick(View v) {
						AddUserTask addUserTask = new AddUserTask();
						TextView username = (TextView)layout.findViewById(R.id.addAccountUsername);
						User u = new User(username.getText().toString());
						u.setUserIcon(UserIcon.values()[icons.getSelectedItemPosition()]);
						u.setPassword(((TextView)layout.findViewById(R.id.addAccountPassword)).getText().toString());
						addUserTask.execute(u);
						addUser.dismiss();
					}
				});
				
				Button cancelButton = (Button)layout.findViewById(R.id.addAccountButtonCancel);
				cancelButton.setOnClickListener(new Button.OnClickListener() {
					@Override
					public void onClick(View v) {
						addUser.dismiss();
					}
				});
				
				addUser.showAtLocation(layout, Gravity.CENTER, 0, 0);
			}        	
        });
        
        GetUsersTask getUsersTask = new GetUsersTask();
        getUsersTask.execute((Void) null);
    }
      
    /**
     * Generates the list of drawables for the icons the user can select from when
     * creating a new account.
     * 
     * @return the list of drawables representing all user icons available
     */
    private List<HashMap<String, Drawable>> getIconList() {
    	List<HashMap<String, Drawable>> iconList = new ArrayList<HashMap<String, Drawable>>();
    	
    	for (int i = 0; i < 12; i++) {
            HashMap<String, Drawable> map = new HashMap<String, Drawable>();
            map.put("Icon", this.getResources().getDrawable(UserIcon.values()[i].getIconId()));
            iconList.add(map);
        }
        return iconList;
    }

    /**
     * An asynchronous task used to add a user to the database.
     * @author Katherine Tornwall
     */
    private class AddUserTask extends AsyncTask<User, Void, String> {

    	/**
    	 * {@inheritDoc}
    	 */
		@Override
		protected String doInBackground(User... params) {
			UserDatabaseHelper db = new UserDatabaseHelper(LoginActivity.this);
			if(params[0] != null)
				return db.addUser(params[0]);
			return null;
		}
		
		/**
    	 * {@inheritDoc}
    	 */
		@Override
		protected void onPostExecute(String result) {
			if(result != null) {
				LayoutInflater inflater = getLayoutInflater();
				final View layout = inflater.inflate(R.layout.add_error_message, null);
				final PopupWindow errorWindow = new PopupWindow(layout, LayoutParams.FILL_PARENT, 
						LayoutParams.FILL_PARENT, true);
				
				TextView errorText = (TextView)layout.findViewById(R.id.errorText);
				errorText.setText(result);
				
				Button okButton = (Button)layout.findViewById(R.id.errorButtonOK);
				okButton.setOnClickListener(new Button.OnClickListener() {
					@Override
					public void onClick(View v) {
						errorWindow.dismiss();
					}
				});
				
				errorWindow.showAtLocation(layout, Gravity.CENTER, 0, 0);
			}
	    }
    }
    
    /**
     * An asynchronous task used to get all of the users on this phone into an
     * array list of User objects.
     * @author Katherine Tornwall
     */
    private class GetUsersTask extends AsyncTask<Void, Void, ArrayList<User>> {

    	/**
    	 * {@inheritDoc}
    	 */
		@Override
		protected ArrayList<User> doInBackground(Void... params) {
			UserDatabaseHelper db = new UserDatabaseHelper(LoginActivity.this);
			ArrayList<User> list = null;
			User[] u = db.getUsers();
			if(u != null) {
				list = new ArrayList<User>();
				for(int i = 0; i < u.length; i++) {
					list.add(u[i]);
				}
			}
			
			return list;
		}
		
		/**
    	 * {@inheritDoc}
    	 */
		@Override
		protected void onPostExecute(ArrayList<User> result) {
			if(result == null) return;
			
			ListView list = (ListView)LoginActivity.this.findViewById(R.id.listViewLoginUsers);
			UserAdapter adapter = (UserAdapter)list.getAdapter();
			for(int i = 0; i < result.size(); i++) {
				adapter.add(result.get(i));
			}
	     }
    }
    
    /**
     * The adapter for the spinner to show the icons for the user to select when
     * creating a new account.
     * 
     * @author Katherine Tornwall
     */
    private class IconAdapter extends SimpleAdapter {
    	/**
    	 * {@inheritDoc}
    	 */
	    public IconAdapter(Context context, List<? extends Map<String, ?>> data,
	            int resource, String[] from, int[] to) {
	        super(context, data, resource, from, to);
	    }
	
	    /**
    	 * {@inheritDoc}
    	 */
	    @Override
	    public View getView(int position, View convertView, ViewGroup parent) {
	        if (convertView == null) {
	            convertView = LoginActivity.this.getLayoutInflater().inflate(R.layout.icon, null);
	        }
	        @SuppressWarnings("unchecked")
			HashMap<String, Drawable> data = (HashMap<String, Drawable>) getItem(position);
	        ImageView icon = (ImageView)convertView.findViewById(R.id.spinnerIcon);
	        icon.setImageDrawable(data.get("Icon"));
	        return convertView;
	    }
	    
	    /**
    	 * {@inheritDoc}
    	 */
	    @Override
	    public View getDropDownView(int position, View convertView, ViewGroup parent) {
	        if (convertView == null) {
	            convertView = LoginActivity.this.getLayoutInflater().inflate(R.layout.icon, null);
	        }
	        @SuppressWarnings("unchecked")
			HashMap<String, Drawable> data = (HashMap<String, Drawable>) getItem(position);
	        ImageView icon = (ImageView)convertView.findViewById(R.id.spinnerIcon);
	        icon.setImageDrawable(data.get("Icon"));
	        return convertView;
	    }
    }
    
    /**
     * The adapter used to show the list of users in the login screen. 
     * 
     * @author Katherine Tornwall
     */
    private class UserAdapter extends ArrayAdapter<User> {
    	/**
    	 * The list of users to be shown.
    	 */
		private ArrayList<User> items;

		/**
    	 * {@inheritDoc}
    	 */
		public UserAdapter(Context context, int textViewResourceId, ArrayList<User> items) {
			super(context, textViewResourceId, items);
			this.items = items;
		}

		/**
    	 * {@inheritDoc}
    	 */
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				v = vi.inflate(R.layout.user_layout, null);
			}
			User u = items.get(position);
			if (u != null) {
				TextView username = (TextView) v.findViewById(R.id.textUsername);
				TextView rating = (TextView) v.findViewById(R.id.textRating);
				TextView winLoss = (TextView) v.findViewById(R.id.textWinLoss);
				ImageView userIcon = (ImageView) v.findViewById(R.id.imageUserIcon);

				username.setText("" + u.getUsername());
				rating.setText("" + u.getRating());
				winLoss.setText("" + u.getWins() + " W - " + u.getLosses() + " L - " +
						u.getDraws() + " D");
				userIcon.setImageResource(u.getUserIcon().getIconId());
			}
			return v;
		}
	}
}
